---@class Utility : Object
local Utility = {}

--- 根据路径读取技能
---@param packagename string
Utility.loadSkillSkelsByPackage = function(package,packagename)
    local path = "./packages/glory_days/pkg/"..packagename.."/skills"
    local skels = {}
    local normalized_dir = path
        :gsub("^%.+/", "")
        :gsub("/+$", "")
        :gsub("/", ".")
    for _, filename in ipairs(FileIO.ls(path)) do
        -- 别加载下划线开头的模板技能哈
        if filename:sub(-4) == ".lua" and filename ~= "init.lua" and not filename:startsWith("_") then
        local skel = Pcall(require, normalized_dir .. "." .. filename:sub(1, -5))
            if skel then
                -- 如果返回了一个skel表
                if type(skel) == "table" and not skel.class then
                    for _, v in ipairs(skel) do
                        table.insert(skels, v)
                    end
                else
                    table.insert(skels, skel)
                end
            end
        end
    end
    package:loadSkillSkels(skels)
end

--- 获取玩家模式胜负场
--- @param room Room @ 房间
--- @param player ServerPlayer @ 玩家
--- @param mode string @ 模式
--- @return playerdate table @ 玩家数据
Utility.getModeWinLosedata = function (room, player, mode)
    local modename = room.settings.gameMode
    room.settings.gameMode = mode
    --room.room:updatePlayerWinRate(player.id, mode, "rebel", 0) --随便更新一下
    local playerdata = player._splayer:getGameData()

    local tot, win = playerdata:at(0), playerdata:at(1)
    local ret = {tot, win}
    room.settings.gameMode = modename --恢复
    return ret
end

--- 获取指定格式的日期整数
local function getFormattedDate(format)
    local timeTable = os.date("*t")
    
    if format == "YYYYMMDD" then
        return timeTable.year * 10000 + timeTable.month * 100 + timeTable.day
    elseif format == "YYMMDD" then
        return (timeTable.year % 100) * 10000 + timeTable.month * 100 + timeTable.day
    elseif format == "YYYYMM" then
        return timeTable.year * 100 + timeTable.month
    else
        -- 默认返回 YYYYMMDD 格式
        return timeTable.year * 10000 + timeTable.month * 100 + timeTable.day
    end
end

--改变玩家帅点，最低降到0
---@param room Room @ 房间
---@param player ServerPlayer @ 玩家
---@param change integer @ 改变量
Utility.changePlayerRank = function (room,player,change)
    if player.id < 1 then return end

    local data = player:getGlobalSaveState("glory_days") or {}
    local count = data["glory_days_shuaidian"] or 0
    count = count + change
    data["glory_days_shuaidian"] = count
    player:saveGlobalState("glory_days", data)

    if change > 0 then
        local rank = Utility.getOfficialLevel(room, player)
        room:doAnimate("SuperLightBox", {
            path = "packages/glory_days/qml/AcquireRanks.qml",
            data = {
                rank = rank,
                num = change * 10
            }
        }, {player})
    end

end

--[[
--- 获取（计算）玩家帅点（旧版）
--- @param room Room @ 房间
--- @param player ServerPlayer @ 玩家
--- @return integer @ 帅点
Utility.getOldOfficialRank = function (room, player)
    local count = 0

    if player.id < 1 then return 0 end

    local playerdata = Utility.getModeWinLosedata(room, player, "glory_days_rank")
    if type(playerdata[1]) == "number" then
        local total, win = playerdata[1], playerdata[2]
        local lose = total - win
        count = count + math.max(0, win - lose)
    end

    return count * 10
end
]]--

--- 获取（计算）玩家帅点
--- @param room Room @ 房间
--- @param player ServerPlayer @ 玩家
--- @return integer @ 帅点
Utility.getOfficialRank = function (room, player)
    if player.id < 1 then return 0 end

    local data = player:getGlobalSaveState("glory_days") or {}

    local count = data["glory_days_shuaidian"] or 0

    --[[ if count == 0 then
        count = count + Utility.getOldOfficialRank(room, player)/10
    end ]]--

    local qiandao = data["glory_days_qiandao"] or {}

    local current_date = "glory_days_qiandao" + tostring(getFormattedDate())
    if not qiandao[current_date] then
        qiandao[current_date] = true
        count = count + 50
        player:doNotify("GameLog", {
            type = "#glory_days_rank_log",
            from = player.id,
            toast = true,
        })
    end

    data["glory_days_shuaidian"] = count
    data["glory_days_qiandao"] = qiandao

    player:saveGlobalState("glory_days", data)

    return count * 10
end

--- 获取（计算）玩家官阶
--- @param room Room @ 房间
--- @param player ServerPlayer @ 玩家
--- @param returnLevel? boolean @ 返回等级（数字）
--- @return string|integer @ 官阶
Utility.getOfficialLevel = function (room, player, returnLevel)
    local ranks = {"dajiangjun","biaoqijiangjun","cheqijiangjun","weijiangjun",
        "guoduhu","guohujun","shangjiangjun","jiangjun",
        "pianjiangjun","langjiang","xiaowei","xiaozu"
    }
    local rankNums = {350000, 250000, 200000, 160000, 130000, 80000, 60000, 52000, 12000, 8000, 4000, 0}
    local count = Utility.getOfficialRank(room, player)
    local cpRank = "xiaozu"
    local level = 12
    for i = 1, 12, 1 do
        if count >= rankNums[i] then
            cpRank = ranks[i]
            level = i
            break
        end
    end
    if returnLevel then
        return level
    else
        return cpRank
    end
end

--- 弹出成就
--- @param room Room @ 游戏房间
--- @param type? string|AchievementType @ 成就框样式
--- @param width? integer @ 成就框宽度，默认250
--- @param height? integer @ 成就框高度，默认50
--- @param title string @ 成就标题
--- @param context string @ 成就文本
--- @param imgSrc string|AchievementImgSrc @ 成就图片
--- @param players? ServerPlayer[] @ 要弹出成就的玩家们，默认为全员
--- @param repeatable? boolean @ 是否可重复达成，默认可重复
Utility.addAchievement = function (room, type, width, height, title, context, imgSrc, players, repeatable)

    type = type or "steam"
    width = width or 250
    height = height or width/5
    title = title or "Hellow World!"
    context = context or "Welcome to my world!"
    imgSrc = imgSrc or "general:guanyu"
    players = players or room.players
    repeatable = repeatable or true

    local viewPlayers = {}

    for _, cp in pairs(players) do
        local cpData = cp:getGlobalSaveState("glory_days") or {}
        local achievements = cpData["glory_days_achievements"] or {}

        if not achievements[title] or repeatable then
            if not achievements[title] then
                achievements[title] = {title = title, context = context, imgSrc = imgSrc, repeatable = repeatable, num = 1, time = getFormattedDate()}
            else
                achievements[title].num = achievements[title].num + 1
            end
            table.insert(viewPlayers, cp)

            cpData["glory_days_achievements"] = achievements
            cp:saveGlobalState("glory_days", cpData)
        end
    end

    room:doAnimate("SuperLightBox", {
        path = "packages/glory_days/qml/Achievement.qml",
        data = {
            type = type,
            width = width,
            height = height,
            title = title,
            context = context,
            imgSrc = imgSrc
        }
    }, viewPlayers)

end

--- 玩家数据
--- @alias playerdate table

--- 内置成就框样式，默认为steam样式
--- @alias AchievementType ("steam" | "mc")

--- 成就图片格式
--- @alias AchievementImgSrc
---| "path:<文件路径>" # 引用某图片，以"path:"开头，后接文件路径
---| "general:<武将id>" # 引用武将插图，以"general:"开头，后接武将id

return Utility